/*
 * Copyright (c) 2009-2011, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/directx9/DirectXSystem.h"

#include <DxErr.h>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dxerr.lib")

namespace alkes {

static struct {
    D3DFORMAT   dxformat;
    PixelFormat alformat;
} s_format_table[] = {

    // 32 bits
    {D3DFMT_A8B8G8R8,   AL_PIXEL_FORMAT_RGBA8888},
    {D3DFMT_X8B8G8R8,   AL_PIXEL_FORMAT_RGBX8888},

    // 24 bits
    {D3DFMT_R8G8B8,     AL_PIXEL_FORMAT_RGB888},

    // 16 bits
    {D3DFMT_R5G6B5,     AL_PIXEL_FORMAT_RGB565},
    {D3DFMT_A4R4G4B4,   AL_PIXEL_FORMAT_RGBA4444},
    {D3DFMT_X4R4G4B4,   AL_PIXEL_FORMAT_RGBX4444},

    // 8 bits
    {D3DFMT_A8,         AL_PIXEL_FORMAT_A8},

    // invalid 
    {D3DFMT_UNKNOWN,    AL_PIXEL_FORMAT_UNKNOWN}
};

PixelFormat dxformat2alformat(D3DFORMAT dxformat)
{
    int i;
    for (i = 0; i < sizeof(s_format_table)/sizeof(s_format_table[0]) - 1; ++i)
    {
        if (s_format_table[i].dxformat == dxformat)
            break;
    }

    return s_format_table[i].alformat;
}

D3DFORMAT alformat2dxformat(PixelFormat alformat)
{
    int i;
    for (i = 0; i < sizeof(s_format_table)/sizeof(s_format_table[0]) - 1; ++i)
    {
        if (s_format_table[i].alformat == alformat)
            break;
    }

    return s_format_table[i].dxformat;
}

#define FLAG_LOG(member, name, flag)  AL_DBG(name "=%d", 0 != (caps.member&flag))

void printDeviceCaps(IDirect3DDevice* device)
{
    D3DCAPS9 caps;
    device->GetDeviceCaps(&caps);

    AL_DBG("MaxAnisotropy=%d", caps.MaxAnisotropy);

#define FILTER_LOG(type)    FLAG_LOG(TextureFilterCaps, #type, type)
    AL_DBG("TextureFilterCaps=%08x", caps.TextureFilterCaps);
    FILTER_LOG(D3DPTFILTERCAPS_MAGFPOINT);
    FILTER_LOG(D3DPTFILTERCAPS_MAGFLINEAR);
    FILTER_LOG(D3DPTFILTERCAPS_MAGFANISOTROPIC);
    FILTER_LOG(D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD);
    FILTER_LOG(D3DPTFILTERCAPS_MAGFGAUSSIANQUAD);

    FILTER_LOG(D3DPTFILTERCAPS_MINFPOINT);
    FILTER_LOG(D3DPTFILTERCAPS_MINFLINEAR);
    FILTER_LOG(D3DPTFILTERCAPS_MINFANISOTROPIC);
    FILTER_LOG(D3DPTFILTERCAPS_MINFPYRAMIDALQUAD);
    FILTER_LOG(D3DPTFILTERCAPS_MINFGAUSSIANQUAD);

    FILTER_LOG(D3DPTFILTERCAPS_MIPFPOINT);
    FILTER_LOG(D3DPTFILTERCAPS_MIPFLINEAR);

#define SRCBLEND_LOG(type)  FLAG_LOG(SrcBlendCaps, #type, type)
#define DESTBLEND_LOG(type)  FLAG_LOG(DestBlendCaps, #type, type)
    AL_DBG("SrcBlendCaps=%08x", caps.SrcBlendCaps);
    SRCBLEND_LOG(D3DPBLENDCAPS_BLENDFACTOR);
    SRCBLEND_LOG(D3DPBLENDCAPS_BOTHINVSRCALPHA);
    SRCBLEND_LOG(D3DPBLENDCAPS_BOTHSRCALPHA);
    SRCBLEND_LOG(D3DPBLENDCAPS_DESTALPHA);
    SRCBLEND_LOG(D3DPBLENDCAPS_DESTCOLOR);
    SRCBLEND_LOG(D3DPBLENDCAPS_INVDESTALPHA);
    SRCBLEND_LOG(D3DPBLENDCAPS_INVDESTCOLOR);
    SRCBLEND_LOG(D3DPBLENDCAPS_INVSRCALPHA);
    SRCBLEND_LOG(D3DPBLENDCAPS_INVSRCCOLOR);
    SRCBLEND_LOG(D3DPBLENDCAPS_ONE);
    SRCBLEND_LOG(D3DPBLENDCAPS_SRCALPHA);
    SRCBLEND_LOG(D3DPBLENDCAPS_SRCALPHASAT);
    SRCBLEND_LOG(D3DPBLENDCAPS_SRCCOLOR);
    SRCBLEND_LOG(D3DPBLENDCAPS_ZERO);
    AL_DBG("DestBlendCaps=%08x", caps.DestBlendCaps);
    DESTBLEND_LOG(D3DPBLENDCAPS_BLENDFACTOR);
    DESTBLEND_LOG(D3DPBLENDCAPS_BOTHINVSRCALPHA);
    DESTBLEND_LOG(D3DPBLENDCAPS_BOTHSRCALPHA);
    DESTBLEND_LOG(D3DPBLENDCAPS_DESTALPHA);
    DESTBLEND_LOG(D3DPBLENDCAPS_DESTCOLOR);
    DESTBLEND_LOG(D3DPBLENDCAPS_INVDESTALPHA);
    DESTBLEND_LOG(D3DPBLENDCAPS_INVDESTCOLOR);
    DESTBLEND_LOG(D3DPBLENDCAPS_INVSRCALPHA);
    DESTBLEND_LOG(D3DPBLENDCAPS_INVSRCCOLOR);
    DESTBLEND_LOG(D3DPBLENDCAPS_ONE);
    DESTBLEND_LOG(D3DPBLENDCAPS_SRCALPHA);
    DESTBLEND_LOG(D3DPBLENDCAPS_SRCALPHASAT);
    DESTBLEND_LOG(D3DPBLENDCAPS_SRCCOLOR);
    DESTBLEND_LOG(D3DPBLENDCAPS_ZERO);

#define TEXOP_LOG(type)  FLAG_LOG(TextureOpCaps, #type, type)
    AL_DBG("TextureOpCaps=%08x", caps.TextureOpCaps);
    TEXOP_LOG(D3DTEXOPCAPS_ADD);
    TEXOP_LOG(D3DTEXOPCAPS_ADDSIGNED);
    TEXOP_LOG(D3DTEXOPCAPS_ADDSIGNED2X);
    TEXOP_LOG(D3DTEXOPCAPS_ADDSMOOTH);
    TEXOP_LOG(D3DTEXOPCAPS_BLENDCURRENTALPHA);
    TEXOP_LOG(D3DTEXOPCAPS_BLENDDIFFUSEALPHA);
    TEXOP_LOG(D3DTEXOPCAPS_BLENDFACTORALPHA);
    TEXOP_LOG(D3DTEXOPCAPS_BLENDTEXTUREALPHA);
    TEXOP_LOG(D3DTEXOPCAPS_BLENDTEXTUREALPHAPM);
    TEXOP_LOG(D3DTEXOPCAPS_BUMPENVMAP);
    TEXOP_LOG(D3DTEXOPCAPS_BUMPENVMAPLUMINANCE);
    TEXOP_LOG(D3DTEXOPCAPS_DISABLE);
    TEXOP_LOG(D3DTEXOPCAPS_DOTPRODUCT3);
    TEXOP_LOG(D3DTEXOPCAPS_LERP);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATE);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATE2X);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATE4X);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR);
    TEXOP_LOG(D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA);
    TEXOP_LOG(D3DTEXOPCAPS_MULTIPLYADD);
    TEXOP_LOG(D3DTEXOPCAPS_PREMODULATE);
    TEXOP_LOG(D3DTEXOPCAPS_SELECTARG1);
    TEXOP_LOG(D3DTEXOPCAPS_SELECTARG2);
    TEXOP_LOG(D3DTEXOPCAPS_SUBTRACT);
    AL_DBG("MaxTextureBlendStages=%d", caps.MaxTextureBlendStages);
    AL_DBG("MaxSimultaneousTextures=%d", caps.MaxSimultaneousTextures);
}

HRESULT invokedMethod(HRESULT result, const char* exp)
{
    //AL_DBG("invokedMethod(%s)", exp);
    if (FAILED(result)) {
        AL_ERROR("%s = %s", DXGetErrorString(result), exp);
    }
    return result;
}


}
